(define (cddr s)
  (cdr (cdr s)))

(define (cadr s)
  (car (cdr s))  
)

(define (caddr s)
  (car (cdr (cdr s)))
)


(define (sign num)
  (cond
    ((= num 0) 0)
    ((> num 0) 1)
    ((< num 0) -1)
  )
)


(define (square x) (* x x))

(define (pow x y)
  (if (= y 1)
    x
    (if (even? y)
      (square (pow x (/ y 2)))
      (* (square (pow x (/ (- y 1) 2))) x)
    )
  )
  
)


(define (unique s)
  (if (null? s)
    nil
    (if (null? (cdr s))
      (list (car s))
      (append (list (car s)) (unique (filter (lambda (x) (not (eq? (car s) x))) (cdr s))))
    )
  )
)


(define (replicate x n)
  (define (replicate-iter s t)
    (if (= t n) 
      s
      (replicate-iter (append s (cons x nil)) (+ t 1))
    )
  )
  (replicate-iter nil 0)  
)


(define (accumulate combiner start n term)
  (define (accumulate-helper t)
    (if (= t n)
      (combiner start (term t))
      (combiner (accumulate-helper (+ t 1)) (term t))
    )
  )
  (accumulate-helper 1)
)


(define (accumulate-tail combiner start n term)
  (define (accumulate-iter t res)
    (if (= t n)
      (combiner res (term n))
      (accumulate-iter (+ 1 t) (combiner res (term t)))
    )
  )
  (accumulate-iter 1 start)
)


(define-macro (list-of map-expr for var in lst if filter-expr)
  `(map (lambda (,var) ,map-expr) (filter (lambda (,var) ,filter-expr) ,lst))
)

